import { Client, IMessage, StompSubscription } from '@stomp/stompjs'
import SockJS from 'sockjs-client'
import { rtcAPI, type Call } from '@/api/rtc'

/**
 * WebRTC信令类型
 */
export type SignalingType =
  | 'OFFER'
  | 'ANSWER'
  | 'ICE_CANDIDATE'
  | 'CALL_INVITE'
  | 'CALL_ACCEPT'
  | 'CALL_REJECT'
  | 'CALL_CANCEL'
  | 'CALL_END'
  | 'PARTICIPANT_JOIN'
  | 'PARTICIPANT_LEAVE'
  | 'MEDIA_STATE_CHANGE'

export interface SignalingMessage {
  type: SignalingType
  callId: string
  from: string
  to?: string
  data?: any
}

export interface RTCPeerConnectionConfig {
  iceServers: RTCIceServer[]
}

/**
 * WebRTC连接管理器
 */
export class WebRTCManager {
  private client: Client | null = null
  private peerConnections: Map<string, RTCPeerConnection> = new Map()
  private localStream: MediaStream | null = null
  private subscriptions: Map<string, StompSubscription> = new Map()
  
  private config: RTCPeerConnectionConfig = {
    iceServers: [
      { urls: 'stun:stun.l.google.com:19302' },
      { urls: 'stun:stun1.l.google.com:19302' }
    ]
  }

  // 事件处理器
  private onCallInviteHandler?: (callId: string, from: string) => void
  private onRemoteStreamHandler?: (userId: string, stream: MediaStream) => void
  private onParticipantJoinHandler?: (userId: string) => void
  private onParticipantLeaveHandler?: (userId: string) => void
  private onCallEndHandler?: (callId: string) => void

  /**
   * 连接信令服务器
   */
  connect(token: string): Promise<void> {
    return new Promise((resolve, reject) => {
      this.client = new Client({
        webSocketFactory: () => {
          return new SockJS(`${import.meta.env.VITE_WS_URL || 'http://localhost:8083'}/rtc-ws`)
        },
        connectHeaders: {
          Authorization: `Bearer ${token}`
        },
        onConnect: () => {
          console.log('WebRTC signaling connected')
          
          // 订阅个人信令通道
          this.subscribeToPersonalQueue()
          
          resolve()
        },
        onStompError: (frame) => {
          console.error('STOMP error:', frame)
          reject(new Error('WebRTC connection failed'))
        }
      })

      this.client.activate()
    })
  }

  /**
   * 订阅个人信令队列
   */
  private subscribeToPersonalQueue() {
    if (!this.client) return

    const subscription = this.client.subscribe('/user/queue/rtc-signal', (message: IMessage) => {
      try {
        const signal: SignalingMessage = JSON.parse(message.body)
        this.handleSignalingMessage(signal)
      } catch (error) {
        console.error('Failed to parse signaling message', error)
      }
    })

    this.subscriptions.set('personal', subscription)
  }

  /**
   * 订阅通话频道
   */
  subscribeToCall(callId: string) {
    if (!this.client) return

    const subscription = this.client.subscribe(`/topic/call/${callId}`, (message: IMessage) => {
      try {
        const signal: SignalingMessage = JSON.parse(message.body)
        this.handleSignalingMessage(signal)
      } catch (error) {
        console.error('Failed to parse call message', error)
      }
    })

    this.subscriptions.set(`call-${callId}`, subscription)
  }

  /**
   * 处理信令消息
   */
  private async handleSignalingMessage(signal: SignalingMessage) {
    switch (signal.type) {
      case 'CALL_INVITE':
        this.onCallInviteHandler?.(signal.callId, signal.from)
        break

      case 'OFFER':
        await this.handleOffer(signal)
        break

      case 'ANSWER':
        await this.handleAnswer(signal)
        break

      case 'ICE_CANDIDATE':
        await this.handleIceCandidate(signal)
        break

      case 'PARTICIPANT_JOIN':
        this.onParticipantJoinHandler?.(signal.data.userId)
        break

      case 'PARTICIPANT_LEAVE':
        this.closePeerConnection(signal.from)
        this.onParticipantLeaveHandler?.(signal.from)
        break

      case 'CALL_END':
        this.endCall()
        this.onCallEndHandler?.(signal.callId)
        break

      case 'MEDIA_STATE_CHANGE':
        // 处理媒体状态变化
        console.log('Media state changed:', signal.data)
        break
    }
  }

  /**
   * 启动本地媒体流
   */
  async startLocalStream(video: boolean = true, audio: boolean = true): Promise<MediaStream> {
    try {
      this.localStream = await navigator.mediaDevices.getUserMedia({
        video: video ? { width: 1280, height: 720 } : false,
        audio
      })
      return this.localStream
    } catch (error) {
      console.error('Failed to get local stream:', error)
      throw error
    }
  }

  /**
   * 创建点对点连接
   */
  async createPeerConnection(userId: string): Promise<RTCPeerConnection> {
    const pc = new RTCPeerConnection(this.config)

    // 添加本地流
    if (this.localStream) {
      this.localStream.getTracks().forEach(track => {
        pc.addTrack(track, this.localStream!)
      })
    }

    // ICE候选事件
    pc.onicecandidate = (event) => {
      if (event.candidate) {
        this.sendSignal({
          type: 'ICE_CANDIDATE',
          callId: this.currentCallId!,
          from: this.currentUserId!,
          to: userId,
          data: { candidate: event.candidate }
        })
      }
    }

    // 接收远程流
    pc.ontrack = (event) => {
      console.log('Received remote stream from:', userId)
      this.onRemoteStreamHandler?.(userId, event.streams[0])
    }

    // ICE连接状态变化
    pc.oniceconnectionstatechange = () => {
      console.log('ICE connection state:', pc.iceConnectionState)
      if (pc.iceConnectionState === 'disconnected' || pc.iceConnectionState === 'failed') {
        this.closePeerConnection(userId)
      }
    }

    this.peerConnections.set(userId, pc)
    return pc
  }

  /**
   * 创建Offer
   */
  async createOffer(userId: string): Promise<void> {
    const pc = await this.createPeerConnection(userId)
    const offer = await pc.createOffer()
    await pc.setLocalDescription(offer)

    this.sendSignal({
      type: 'OFFER',
      callId: this.currentCallId!,
      from: this.currentUserId!,
      to: userId,
      data: { sdp: offer }
    })
  }

  /**
   * 处理Offer
   */
  private async handleOffer(signal: SignalingMessage) {
    const pc = await this.createPeerConnection(signal.from)
    await pc.setRemoteDescription(new RTCSessionDescription(signal.data.sdp))
    
    const answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    this.sendSignal({
      type: 'ANSWER',
      callId: signal.callId,
      from: this.currentUserId!,
      to: signal.from,
      data: { sdp: answer }
    })
  }

  /**
   * 处理Answer
   */
  private async handleAnswer(signal: SignalingMessage) {
    const pc = this.peerConnections.get(signal.from)
    if (pc) {
      await pc.setRemoteDescription(new RTCSessionDescription(signal.data.sdp))
    }
  }

  /**
   * 处理ICE候选
   */
  private async handleIceCandidate(signal: SignalingMessage) {
    const pc = this.peerConnections.get(signal.from)
    if (pc && signal.data.candidate) {
      await pc.addIceCandidate(new RTCIceCandidate(signal.data.candidate))
    }
  }

  /**
   * 发送信令消息
   */
  private sendSignal(signal: SignalingMessage) {
    if (!this.client) return

    let destination: string
    switch (signal.type) {
      case 'OFFER':
        destination = '/app/rtc/offer'
        break
      case 'ANSWER':
        destination = '/app/rtc/answer'
        break
      case 'ICE_CANDIDATE':
        destination = '/app/rtc/ice-candidate'
        break
      default:
        return
    }

    this.client.publish({
      destination,
      body: JSON.stringify(signal)
    })
  }

  /**
   * 切换音频
   */
  toggleAudio(enabled: boolean) {
    if (this.localStream) {
      this.localStream.getAudioTracks().forEach(track => {
        track.enabled = enabled
      })
    }
  }

  /**
   * 切换视频
   */
  toggleVideo(enabled: boolean) {
    if (this.localStream) {
      this.localStream.getVideoTracks().forEach(track => {
        track.enabled = enabled
      })
    }
  }

  /**
   * 屏幕共享
   */
  async startScreenShare(): Promise<MediaStream> {
    try {
      const screenStream = await navigator.mediaDevices.getDisplayMedia({
        video: true,
        audio: false
      })

      // 替换所有peer connection中的视频轨道
      const videoTrack = screenStream.getVideoTracks()[0]
      this.peerConnections.forEach(pc => {
        const sender = pc.getSenders().find(s => s.track?.kind === 'video')
        if (sender) {
          sender.replaceTrack(videoTrack)
        }
      })

      return screenStream
    } catch (error) {
      console.error('Screen share failed:', error)
      throw error
    }
  }

  /**
   * 关闭点对点连接
   */
  private closePeerConnection(userId: string) {
    const pc = this.peerConnections.get(userId)
    if (pc) {
      pc.close()
      this.peerConnections.delete(userId)
    }
  }

  /**
   * 结束通话
   */
  endCall() {
    // 关闭所有peer connections
    this.peerConnections.forEach(pc => pc.close())
    this.peerConnections.clear()

    // 停止本地流
    if (this.localStream) {
      this.localStream.getTracks().forEach(track => track.stop())
      this.localStream = null
    }
  }

  /**
   * 断开连接
   */
  disconnect() {
    this.endCall()
    
    // 取消所有订阅
    this.subscriptions.forEach(sub => sub.unsubscribe())
    this.subscriptions.clear()

    // 断开WebSocket
    if (this.client) {
      this.client.deactivate()
      this.client = null
    }
  }

  // 当前通话信息（简化处理）
  private currentCallId: string | null = null
  private currentUserId: string | null = null

  setCurrentCall(callId: string, userId: string) {
    this.currentCallId = callId
    this.currentUserId = userId
  }

  // 事件处理器设置
  onCallInvite(handler: (callId: string, from: string) => void) {
    this.onCallInviteHandler = handler
  }

  onRemoteStream(handler: (userId: string, stream: MediaStream) => void) {
    this.onRemoteStreamHandler = handler
  }

  onParticipantJoin(handler: (userId: string) => void) {
    this.onParticipantJoinHandler = handler
  }

  onParticipantLeave(handler: (userId: string) => void) {
    this.onParticipantLeaveHandler = handler
  }

  onCallEnd(handler: (callId: string) => void) {
    this.onCallEndHandler = handler
  }
}

export const webrtcManager = new WebRTCManager()
